\documentclass[12pt]{report}
\usepackage{geometry}
\geometry{a4paper,scale=0.8}
\usepackage{longtable}
\usepackage{url}
\usepackage{listings}
\usepackage{graphicx}
\usepackage{float}
\usepackage{titlesec}
\usepackage{CJK}
\begin{CJK}{UTF8}{gkai}
%\titleformat{\chapter}[hang]{\centering\Huge\bfseries}{\chaptername}{1em}{}
%\renewcommand{\chaptername}{第\CJKnumber{thechapter}章}
\title{A008 linux0.01源码修改总结}
\author{Chuzy}
\date{2020/12/13}

\lstset{
    basicstyle          =   \small\ttfamily,          % 基本代码风格
    keywordstyle        =   \bfseries,          % 关键字风格
    commentstyle        =   \rmfamily\itshape,  % 注释的风格，斜体
    stringstyle         =   \ttfamily,  % 字符串风格
    flexiblecolumns,                % 别问为什么，加上这个
    numbers             =   left,   % 行号的位置在左边
    showspaces          =   false,  % 是否显示空格，显示了有点乱，所以不现实了
    numberstyle         =   \ttfamily,    % 行号的样式，小五号，tt等宽字体
    showstringspaces    =   false,
    captionpos          =   t,      % 这段代码的名字所呈现的位置，t指的是top上面
    frame               =   lrtb,   % 显示边框
    columns         =   flexible,     
    breaklines      =   true,
    language        =  [ANSI]C,
    escapeinside=``
}


%以上部分叫做"导言区",下面才开始写正文
\begin{document}

%先插入标题
\maketitle
\tableofcontents
\newpage 
\chapter{概述}
经过前面7章的学习，我们加载了linux0.01的内核，并且编译和执行了我们自己的应用，打印出我们第一个Hello World。linux0.01内核学习的使命基本完成。本章总结一下我们重新编译linux0.01内核都走过了那些坑。

\chapter{语法上的变化点}
\section{16位汇编编译器注释格式变化}
编译器变化，编译不再识别$|$为注释，需要替换成$!$ ，影响boot/boot.s。
\section{32位汇编和C原因变量定义变化}
C变量编译后不再自动添加\_ ，所有汇编使用C变量或函数定义的地方都需要替换。为了简单，可以统一把\_ 去掉。
\begin{lstlisting}[breaklines]
`如`
.globl _idt,_gdt,_pg_dir
_pg_dir:
`替换为`
.globl idt,gdt,pg_dir
pg_dir:
\end{lstlisting}
\section{编译器需显示定义程序入口}
影响boot/head.s，startup\_32 需要放到.globl中。
\begin{lstlisting}[breaklines]
.globl idt,gdt,pg_dir,startup_32
\end{lstlisting}
\section{编译器对align的定义变化}
影响多个文件
align n的定义有原来的2$^n$对齐，改为n对齐
\begin{lstlisting}[breaklines]
`如`
.align 2
`替换为`
.align 4
\end{lstlisting}
\section{嵌入式汇编使用上的变化}
影响多个文件
\begin{lstlisting}[breaklines]
`如`
			__asm__("cld\n\t"
				"rep\n\t"
				"movsl\n\t"
				"movl _columns,%1\n\t"
				"rep\n\t"
				"stosw"
				::"a" (0x0720),
				"c" ((lines-1)*columns>>1),
				"D" (SCREEN_START),
				"S" (origin)
				:"cx","di","si");
`需去掉最后一行`				
			__asm__("cld\n\t"
				"rep\n\t"
				"movsl\n\t"
				"movl _columns,%1\n\t"
				"rep\n\t"
				"stosw"
				::"a" (0x0720),
				"c" ((lines-1)*columns>>1),
				"D" (SCREEN_START),
				"S" (origin));
\end{lstlisting}
\section{文件中定义的inline函数前的extern替换为static}
影响多个文件
\begin{lstlisting}[breaklines]
extern inline unsigned char get_fs_byte(const char * addr)
{
	unsigned register char _v;

	__asm__ ("movb %%fs:%1,%0":"=r" (_v):"m" (*addr));
	return _v;
}
`需修改为`				
static inline unsigned char get_fs_byte(const char * addr)
{
	unsigned register char _v;

	__asm__ ("movb %%fs:%1,%0":"=r" (_v):"m" (*addr));
	return _v;
}
\end{lstlisting}
\section{部分定义为static的变量需要去掉限制}
主要影响kernel/console.c
\begin{lstlisting}[breaklines]
unsigned long lines=LINES,columns=COLUMNS; //`去掉static限定`
static unsigned long state=0;
static unsigned long npar,par[NPAR];
static unsigned long ques=0;
unsigned char attr=0x07; //`去掉static限定`
\end{lstlisting}

\chapter{非语法上的变化点}
\section{kernel/fork.c中的verify\_area 函数}
get\_base 在编译后出现错误，需要增加volatile关键字。
\begin{lstlisting}[breaklines]
void verify_area(void * addr,int size)
{
	unsigned long start;

	start = (unsigned long) addr;
	size += start & 0xfff;
	start &= 0xfffff000;
	start += get_base(current->ldt[2]);
	while (size>0) {
		size -= 4096;
		write_verify(start);
		start += 4096;
	}
}
`需要修改为`
void verify_area(void * addr,int size)
{
	volatile unsigned long start; //`需要增加volatile关键字`

	start = (unsigned long) addr;
	size += start & 0xfff;
	start &= 0xfffff000;
	start += get_base(current->ldt[2]);
	while (size>0) {
		size -= 4096;
		write_verify(start);
		start += 4096;
	}
}
\end{lstlisting}
\section{kernel/fork.c中的copy\_process 函数}
对一块内存区域进行赋值时，方向错误
\begin{lstlisting}[breaklines]
int copy_process(int nr,long ebp,long edi,long esi,long gs,long none,
		long ebx,long ecx,long edx,
		long fs,long es,long ds,
		long eip,long cs,long eflags,long esp,long ss)
{
	struct task_struct *p;
	int i;
	struct file *f;

	p = (struct task_struct *) get_free_page();
	if (!p)
		return -EAGAIN;
	__asm__ ("cld"::);  //`需要增加cld指令`
	*p = *current;
\end{lstlisting}
\section{kernel/hd.c中的read\_intr 函数}
在读硬盘的时候，需要增加屏蔽中断的处理。
\begin{lstlisting}[breaklines]
static void read_intr(void)
{
	if (win_result()) {
		bad_rw_intr();
		return;
	}
	cli();//`需要增加关中断指令`
	port_read(HD_DATA,this_request->bh->b_data+
		512*(this_request->nsector&1),256);
	this_request->errors = 0;
	if (!(--this_request->nsector)){
		this_request->bh->b_uptodate = 1;
		this_request->bh->b_dirt = 0;
		wake_up(&wait_for_request);
		unlock_buffer(this_request->bh);
		this_request->hd = -1;
		this_request=this_request->next;	
		do_request();	
	}
	sti();//`恢复中断`
}
\end{lstlisting}
\section{init/main.c中的init 函数}
暂时屏蔽掉update的处理，我们现在没有这个外部程序。
\begin{lstlisting}[breaklines]
//	if (!fork())
//		_exit(execve("/bin/update",NULL,NULL));
\end{lstlisting}
\section{tools/build.c}
对elf文件头和段的出来，基本上需要重写。
\section{include/linux/sched.h}
在set\_base 和get\_base 中对dx寄存器的使用存在问题。
\begin{lstlisting}[breaklines]
#define _set_base(addr,base) \
__asm__("movw %%dx,%0\n\t" \
	"rorl $16,%%edx\n\t" \
	"movb %%dl,%1\n\t" \
	"movb %%dh,%2" \
	::"m" (*((addr)+2)), \
	  "m" (*((addr)+4)), \
	  "m" (*((addr)+7)), \
	  "d" (base) \
	:"dx")
`为了保护dx，修改为`	
#define _set_base(addr,base) \
__asm__("push %%edx\n\t" \
	"movw %%dx,%0\n\t" \
	"rorl $16,%%edx\n\t" \
	"movb %%dl,%1\n\t" \
	"movb %%dh,%2\n\t" \
	"pop %%edx\n\t" \
	::"m" (*((addr)+2)), \
	  "m" (*((addr)+4)), \
	  "m" (*((addr)+7)), \
	  "d" (base) \
	)	
\end{lstlisting}	
\begin{lstlisting}[breaklines]
#define _get_base(addr) ({\
unsigned long __base; \
__asm__("movb %3,%%dh\n\t" \
	"movb %2,%%dl\n\t" \
	"shll $16,%%edx\n\t" \
	"movw %1,%%dx" \
	:"=d" (__base) \
	:"m" (*((addr)+2)), \
	 "m" (*((addr)+4)), \
	 "m" (*((addr)+7))); \
__base;})
`为了避免dx出错，先通过bx中转一下`	
#define _get_base(addr) ({\
unsigned long __base; \
__asm__ __volatile__("movw %1,%%bx\n\t" \
	"movb %3,%%dh\n\t" \
	"movb %2,%%dl\n\t" \
	"shll $16,%%edx\n\t" \
	"movw %%bx,%%dx" \
	:"=d" (__base) \
	:"m" (*((addr)+2)), \
	 "m" (*((addr)+4)), \
	 "m" (*((addr)+7))); \
__base;})
\end{lstlisting}	
\section{include/string.h}
在strlen对dx寄存器的使用存在问题。
\begin{lstlisting}[breaklines]
extern inline int strlen(const char * s)
{
register int __res __asm__("cx");
__asm__("cld\n\t"
	"repne\n\t"
	"scasb\n\t"
	"notl %0\n\t"
	"decl %0"
	:"=c" (__res):"D" (s),"a" (0),"0" (0xffffffff):"di");
return __res;
}
`为了保护dx，修改为`	
static inline int strlen(const char * s)
{
register int __res __asm__("cx");
__asm__("push %%edi\n\t"
	"cld\n\t"
	"repne\n\t"
	"scasb\n\t"
	"notl %0\n\t"
	"decl %0\n\t"
	"pop %%edi"
	:"=c" (__res):"D" (s),"a" (0),"0" (0xffffffff));
return __res;
}
\end{lstlisting}	
\chapter{Makefile中的变化点}
\section{16位编译器选项}
\begin{lstlisting}[breaklines]
AS86	=as -0 -a
CC86	=cc -0
LD86	=ld -0
`替换为`	
AS86	=as86 -0 -a
LD86	=ld86 -0
\end{lstlisting}	
\section{32位编译器选项}
\begin{lstlisting}[breaklines]
AS	=gas
LD	=gld
LDFLAGS	=-s -x -M
CC	=gcc
CFLAGS	=-Wall -O -fstrength-reduce -fomit-frame-pointer -fcombine-regs
CPP	=gcc -E -nostdinc -Iinclude
`替换为`	
AS	=as --32
LD	=ld -melf_i386
LDFLAGS	=-s -x -M
CC	=gcc -m32
CFLAGS	=-w -O -fstrength-reduce -fomit-frame-pointer -fno-stack-protector
CPP	=gcc -E -nostdinc -Iinclude
\end{lstlisting}	
\section{主Mailefile增加入口描述}
\begin{lstlisting}[breaklines]
LD	=ld -melf_i386 -e startup_32 -Ttext 0
\end{lstlisting}	
\section{主Mailefile除掉chmem}
\begin{lstlisting}[breaklines]
tools/build: tools/build.c
	$(CC) $(CFLAGS) \
	-o tools/build tools/build.c
	chmem +65000 tools/build
`修改为`
tools/build: tools/build.c
	$(CC) $(CFLAGS) \
	-o tools/build tools/build.c
\end{lstlisting}	
\section{主Mailefile用tmp.sh脚本写入system长度}
\begin{lstlisting}[breaklines]
boot/boot:	boot/boot.s tools/system
	(echo -n "SYSSIZE = (";ls -l tools/system | grep system \
		| cut -c25-31 | tr '\012' ' '; echo "+ 15 ) / 16") > tmp.s
	cat boot/boot.s >> tmp.s
`修改为`
boot/boot:	boot/boot.s tools/system
	(./tmp.sh)
\end{lstlisting}	

\end{CJK}
\end{document}
